#pragma once

#include "QSPrerequisites.h"
#include "QSInput.h"

namespace QS
{
	class Engine
	{
	public:
		virtual ~Engine(){}

		virtual void start()=0;

		virtual GuiSystem* getGuiSystem()=0;
		virtual GameSystem* getGameSystem()=0;
		virtual ScriptSystem* getScriptSystem()=0;
		virtual InputSystem* getInputSystem()=0;
		virtual RenderSystem* getRenderSystem()=0;
		virtual EventSystem* getEventSystem()=0;
		virtual HostSystem* getHostSystem()=0;
	};

	class System
	{
	public:
		System(Engine* e) : mEngine(e){}
		~System(){}

		virtual void initialize()=0;
		virtual void update()=0;
		virtual void shutdown()=0;
	protected:
		Engine* mEngine;
	};

	class GuiSystem : public System
	{
	public:
		GuiSystem(Engine* e) : System(e) {}
		virtual ~GuiSystem(){}

		virtual void printToConsole(const String& message)=0;
	};

	class InputSystem : public System
	{
	public:
		InputSystem(Engine* e) : System(e) {}
		virtual ~InputSystem(){}
	};

	class ScriptSystem : public System
	{
	public:
		ScriptSystem(Engine* e) : System(e) {}
		virtual ~ScriptSystem() {}

		/** Execute a chunk of script code. */
		virtual void execute(const String& chunk)=0;

		/** Runs a script file. */
		virtual void runScript(const String& script)=0;
	};

	class RenderSystem : public System
	{
	public:
		RenderSystem(Engine* e) : System(e) {}
		virtual ~RenderSystem() { }

		virtual bool isRenderWindowClosed() const=0;
		virtual size_t getWindowHandle()=0;
	};

	class HostSystem : public System
	{
	public:
		HostSystem(Engine* e) : System(e) {}
		virtual ~HostSystem(){}

		virtual void showErrorDialog(const String& message)=0;
	};

	class EventSystem : public System
	{
	public:
		EventSystem(Engine* e) : System(e){}
		virtual ~EventSystem(){}

		virtual void queueEvent(const Event& evt)=0;
		virtual void postEvent(const Event& evt)=0;

		virtual void addEventListener(EventListener* l)=0;
		virtual void removeEventListener(EventListener* l)=0;	
	};

	class GameSystem : public System
	{
	public:
		GameSystem(Engine* e) : System(e){}
		virtual ~GameSystem(){}

		virtual void addCommand(const Command& cmd)=0;
		virtual void executeCommand(const String& command)=0;
	};
}